//! Unit test framework in Rust.
//! This module provides functionality to run a series of unit tests, ensuring
//! that memory is properly managed and all allocated memory is freed after each test.

use std::vec::Vec;

/// A trait representing a unit test function.
/// Implementors must provide a `run` method that executes the test.
pub trait UnitTest {
    /// Runs the unit test.
    fn run(&self);
}

/// A struct representing a single unit test.
/// This is a wrapper around a closure that implements the `UnitTest` trait.
pub struct Test {
    test_fn: Box<dyn Fn()>,
}

impl UnitTest for Test {
    fn run(&self) {
        // Turn off any allocation limits that may have been set by a previous test.
        alloc_test_set_limit(-1);

        // Run the test.
        (self.test_fn)();

        // Check that all memory was correctly freed back during the test.
        assert_eq!(alloc_test_get_allocated(), 0, "Memory was not fully freed after the test.");
    }
}

/// Runs a single test.
///
/// # Arguments
///
/// * `test` - A reference to a `Test` struct that implements the `UnitTest` trait.
fn run_test(test: &dyn UnitTest) {
    test.run();
}

/// Runs a series of tests.
///
/// # Arguments
///
/// * `tests` - A vector of `Test` structs that implement the `UnitTest` trait.
pub fn run_tests(tests: Vec<Test>) {
    for test in tests {
        run_test(&test);
    }
}

/// Mock functions for memory allocation testing.
/// These functions should be replaced with actual implementations in a real-world scenario.
fn alloc_test_set_limit(limit: i32) {
    // Mock implementation for setting allocation limit.
}

fn alloc_test_get_allocated() -> i32 {
    // Mock implementation for getting allocated memory.
    0
}

#[cfg(test)]
mod tests {
    use super::*;

    /// A sample test function.
    fn sample_test() {
        // Simulate some test logic.
    }

    #[test]
    fn test_run_single_test() {
        let test = Test {
            test_fn: Box::new(sample_test),
        };
        run_test(&test);
    }

    #[test]
    fn test_run_multiple_tests() {
        let tests = vec![
            Test {
                test_fn: Box::new(sample_test),
            },
            Test {
                test_fn: Box::new(sample_test),
            },
        ];
        run_tests(tests);
    }
}
